class App { constructor( canvasId ) { this.cc = document.getElementById( canvasId ).getContext( "2d" ); this.flg = true; this.svcs = new Array(); let svc = new SVC(); let part1 = new SVC_Part( "part1" ); part1.addJoint( "j1", 50, 50 ); let part2 = new SVC_Part( "part2" ); part2.addJoint( "j1", 100, 0 ); let part3 = new SVC_Part( "part3" ); //build. part1.connect( "j1", part2 ); part2.connect( "j1", part3 ); part1.rotation = 3.14 / 10; part2.rotation = -0.1; part3.rotation = -0.4; svc.setTopPart( part1 ); part1.ox = 50; part1.oy = 50; svc.calc(); this.svcs.push( svc ); } start() { if( 1 ) { this.draw( this.cc ); } if( 0 ) { this.timerId = setInterval( function() { this.draw( this.cc ); this.flg = ! this.flg; }.bind( this ), 500 ); } } stop() { clearInterval( this.timerId ); } draw( cc ) { for( let i = 0; i < this.svcs.length; i++ ) { let svc = this.svcs[ i ]; svc.draw( cc ); } } }//App class SVC { constructor() { this.topPart = null; this.x = 0; this.y = 0; } setTopPart( topPart ) { this.topPart = topPart; //応急的 topPart.parentJoint = { x : 0, y : 0, } } calc() { this.topPart.calc(); } draw( cc ) { this.topPart.draw( cc ); } } class SVC_Part { constructor( title ) { this.title = title; this.jointHash = new Object(); this.rotation = 0; this.abs = new Object(); this.parent = null; this.parentJoint = null; this.children = new Array(); } addJoint( name, x, y ) { let joint = new Object(); joint.name = name; joint.x = x; joint.y = y; this.jointHash[ name ] = joint; } //他のSVC_Partを自身のJointへ接続 connect( jointName, part ) { this.children.push( part ); part.parent = this; part.parentJoint = this.jointHash[ jointName ]; } calc() { //自身の値の絶対座標を求める。 if( ! this.parent ) { //親がない場合は this.abs.x = 0; this.abs.y = 0; this.abs.rotation = this.rotation; } else { //親がある場合は let parentJointAbs = this.parent.abs.jointHash[ this.parentJoint.name ]; this.abs.x = parentJointAbs.x; this.abs.y = parentJointAbs.y; this.abs.rotation = this.parent.abs.rotation + this.rotation; } //各jointの絶対座標を求める。 this.abs.jointHash = new Object(); for( let name in this.jointHash ) { let j = this.jointHash[ name ]; let res = this.mathRotate( j.x, j.y, this.abs.rotation ); this.abs.jointHash[ name ] = { x : this.abs.x + res.X, y : this.abs.y + res.Y, } } //子もcalc() for( let i = 0; i < this.children.length; i++ ) { let child = this.children[ i ]; child.calc(); } }//calc() //SVC_Part draw( cc ) { console.log( this.title + " draw." ); //自身を描画 cc.save(); cc.translate( this.abs.x, this.abs.y ); cc.rotate( this.abs.rotation ); cc.strokeRect( 0, 0, 100, 100 ); cc.restore(); //子を描画 for( let i = 0; i < this.children.length; i++ ) { let child = this.children[ i ]; child.draw( cc ); } //debug. if( 1 ) { //各jointを○で示す for( let name in this.jointHash ) { let joint = this.abs.jointHash[ name ]; cc.beginPath(); cc.arc( joint.x, joint.y, 8, 0, 6.28, false ); cc.closePath(); cc.stroke(); } } }//draw() //--- mathRotate( x, y, theta2 ) { let theta1 = Math.atan2( y, x ); let hankei = Math.sqrt( x * x + y * y ); return { X : Math.cos( theta1 + theta2 ) * hankei, Y : Math.sin( theta1 + theta2 ) * hankei, } } }//SVC_Part